package com.sxbbc.plat.service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.sxbbc.common.core.dto.jz.ZTreeVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.function.common.GetRest;
import com.function.common.RestResponse;
import com.sxbbc.common.basics.exceptions.ThrowJsonException;
import com.sxbbc.common.basics.utils.calculation.CalcuUtils;
import com.sxbbc.common.core.entity.jz.CCustomer;
import com.sxbbc.common.core.service.ICCustomerService;

/**
 * 
 * 用户业务
 * @author Wahyee
 */
@Service
public class CustomerService {
	
	private Logger log = LogManager.getLogger(CustomerService.class);
	
	@Autowired
	private ICCustomerService icCustomerService;
	
	/**
	 * 
	 * 修改推荐人
	 * @param cid 被修改的用户ID
	 * @param parentid 新的推荐人用户ID
	 * @return
	 * @author Wahyee
	 * 推荐关系修改规则：
	 * A新的推荐人 B旧的推荐人 C被推荐人 D被推荐人的直推下级  X=C伞下所有用户 ( *.genes like '旧D.genes%' )
	 * B >> C >> D >> ... >> X 修改后 A >> C >> D >> ... >> X
	 * 
	 * 1.推荐人必须早于被推荐人注册 ，即A.id < C.id
	 * 2.不能相互推荐 ，即A.parentid != C.id
	 * 3.被推荐人的关系链需要修改，即 C.genes = A.genes + A.id 
	 * 3.被推荐人的层数需要修改，即 C.layer = A.layer + 1 
	 * 5.被推荐人的直推下级的关系链需要修改，即D.genes = 新C.genes + C.ID
	 * 6.被推荐人的直推下级的层数需要修改，即D.layer= 新C.layer + 1
	 * 7.被推荐人伞下的用户关系链需要修改，即 X.genes 中旧D.genes替换成新D.genes
	 * 8.被推荐人伞下的用户层数需要修改，即 X.layer - 旧C.layer + 新C.layer
	 */
	public RestResponse  updateParent(Integer cid,Integer parentid) {
		//用户
		CCustomer customer = icCustomerService.getById(cid);
		if(customer == null) {
			return GetRest.getFail("用户信息获取失败，请联系管理员");
		}
		if(CalcuUtils.getInstance().isEquals(customer.getParentid(), parentid)) {
			return GetRest.getFail("该推荐人已经是当前用户的推荐人了");
		}
		log.info("用户ID："+cid +" ，旧的推荐人ID："+customer.getParentid()+" ，新的推荐人ID："+parentid);
		
		//新的推荐人信息
		CCustomer parent = icCustomerService.getById(parentid);
		if(parent == null) {
			return GetRest.getFail("推荐人信息获取失败，请稍候重试");
		}
		if(CalcuUtils.getInstance().isEquals(parent.getParentid(), cid)) {
			return GetRest.getFail("不允许互相推荐");
		}
		
		//旧数据信息
		String oldGenesDown = "";
		if(StringUtils.isNotBlank(customer.getGenes())) {
			oldGenesDown = customer.getGenes() + ","+ customer.getId();
		}else {
			oldGenesDown = String.valueOf(customer.getId());
		}
		Integer oldLayer = customer.getLayer();
		
		// (1)被推荐人的修改
		customer.setParentid(parentid);
		customer.setLayer(parent.getLayer()+1);
		if(StringUtils.isNotBlank(parent.getGenes())) {
			customer.setGenes(parent.getGenes() + "," + parentid);
		}else {
			customer.setGenes(String.valueOf(parentid));
		}
		boolean b = icCustomerService.updateById(customer);
		if(!b) {
			throw new ThrowJsonException("用户信息修改失败");
		}
		
		//新数据信息
		String newGenesDown = customer.getGenes() + "," + customer.getId();
		Integer newLayer = customer.getLayer();
		
		// (2)修改伞下所有数据,包含直推
		QueryWrapper<CCustomer> queryWrapper = new QueryWrapper<CCustomer>();
		queryWrapper.like("genes", oldGenesDown);
		List<CCustomer> list =  icCustomerService.list(queryWrapper);
		for(CCustomer c : list) {
			c.setGenes(c.getGenes().replaceAll(oldGenesDown, newGenesDown));;
			c.setLayer(c.getLayer() - oldLayer + newLayer);
		}
		if(!CollectionUtils.isEmpty(list)) {
			b = icCustomerService.updateBatchById(list);
			if(!b) {
				throw new ThrowJsonException("下级用户信息修改失败");
			}
		}
		log.info("关系链：【旧】"+oldGenesDown +" 【新】"+newGenesDown);
		log.info("层级：【旧】"+oldLayer+" 【新】"+ newLayer);
		log.info("伞下用户ID列表："+list.stream().map(x -> x.getId()).collect(Collectors.toList()));
		return GetRest.getSuccess("修改成功");
	}

    public List<ZTreeVo> selectMyTeam(Integer id) {
		CCustomer customer = icCustomerService.getById(id);
		List<CCustomer> list = icCustomerService.queryTeam(customer);
		List<ZTreeVo> returnList = new ArrayList<ZTreeVo>();
		for (CCustomer item : list) {
			ZTreeVo self = new ZTreeVo();
			self.setId(item.getId().toString());
			self.setpId(item.getParentid().toString());
			self.setName(item.getNickName() + " / " + item.getPhone());
			returnList.add(self);
		}
		ZTreeVo self = new ZTreeVo();
		self.setId(customer.getId().toString());
		self.setpId(customer.getParentid() == null ? "0" : customer.getParentid().toString());
		self.setName(customer.getNickName() + " / " + customer.getPhone());
		returnList.add(self);
		return returnList;
    }
}
